iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 28
0
Google Developers Machine Learning

AI可以分析股票嗎?系列 第 28

偏門RL實測 :: 用超簡單股票交易模擬器來訓練模型

  • 分享至 

  • xImage
  •  

零、引言

在上篇「沒有實作所以只好講幹話系列(四) :: 淺談Reinforcement Learning (RL)」的最後,我提到我想要使用loss的方法去更新模型,不是透過Reinforcement Learning或是一般的訓練方式,我並沒有使用DQN或是DDPG (因為還沒看Orz...) 為此,對於「超級簡略的單股買賣模擬器」的環境必須要修改一下,以及如何定義我們的loss(就是reward的相反)。 在這篇,我並不會將state回傳至模型更新,單純只有loss,如果這樣的方法也是可行的話,那就 ~ WOW ~ !

強調,這並不一定會有結果,因為確實沒人這麼做過,但我卻非常好奇XD 總之,讓我們開始吧 !

一、keras中自定義loss

之前有寫一篇「沒有實作所以只好講幹話系列(一) :: 從loss到梯度下降」提到最常使用的loss有兩種 : mean squared errorcross entropy其可以滿足大部分的模型訓練需求。

那為什麼還要自定義loss function ?

在許多不同的情況下,我們可能希望對loss處理,如online hard example,一個對loss做「權重放大」的方法。 如果我們只有使用keras內建的loss function,就不能達到這樣的效果。 那麼,怎麼自定義loss呢?

-> 基本架構

要自定義loss,首先要先了解訓練過程中,keras會丟什麼樣的資料給loss function

  • y_true
    • 你的答案
  • y_pred
    • 當下模型的輸出

就這樣,沒了@@

所以如果我們想要自定義loss,只要有這麼一個格式就能建立最基本的「自定義loss function」囉 !

def myLoss_DerLa(y_true, y_pred):
    ...
    ...
    ...
    return your_loss_der_la # <- 這邊必須回傳一個tensor

很簡單吧! 至於我上面說一定要回傳一個tensor我會在下方有解釋 ~

那麼我們再來進階一步XD

二、導入環境來取得loss

想要實作在keras中的環境其實非常困難,尤其還要自定義loss中的環境。

  • 有兩個方法
    • 使用這個「keras-rl
    • tf.keras.backend把你的環境全部改寫進自定義的loss function ...

太麻煩了吧 喂 ~ 前者還要多摸一個套件,後者光簡單的環境都會寫到發癲...

當然麻煩,因為keras中並沒有支援py_function

只要想辦法使用py_function就可以了嗎?

對,在「自定義loss」中,因為是用迭代運算,所以只能支援tensor的運算方式。 在剛開始跑程式的時候,就會先丟一個「空」的y_truey_pred進到「自定義loss」函數中,如果不是tensor運算式,一開始的執行中,因為丟進來的是「空」,所以運算出錯。

那麼可以用tf.py_function將整個「自定義loss」包起來嗎? 在keras之下

可以的,所以實作上就可以有很大個改變

-> py_function使用

  • 優點
    • 可以實現一般的運算是,最大的好處我們可以這樣簡單地實現loop或是numpy運算
  • 缺點
    • 計算loss就不是使用GPU而是單純的CPU,在大的data output(如 : GAN)等計算上會慢很多

看到這樣的優點,當然要使用一下啦XD 缺點什麼得先放下吧,我們用不到 (笑

  • 其架構和使用方式都很簡單
    • new_function = tf.py_function(your_function, [function input], Tout=<type output>)
    • 第一個輸入就是你想要包起來的函數,第二個輸入則是你的函數的inputTout則是定義輸出的格式

所以只要這樣包起來...

def myLoss_DerLa(y_true, y_pred):
    ...
    ...
    ...
    return your_loss_der_la # <- 這邊必須回傳一個tensor
    
def myLoss(y_true, y_pred):
    return tf.py_function(myLoss_DerLa, [y_true, y_pred], Tout=tf.float32)

就可囉~

三、接下來...

在開頭,我想做的是一個很特別的事情,就是直接把env輸出當作我的loss

這樣真的可以嗎?

我認為loss就只是 一個數字專門打臉你的機器人「你預測的有多不準」 ,但這只是理論上,實際上到底可不可以,還必須要測試看看... 我們先對環境做升級吧 !

1. 環境的loss

我所定義的環境的loss希望得到「當下的資產」減去「過去的資產」,但這其實會有問題,我們如果做「買」,當下資產其實是下降的,因為手續費是使用的狀態。 所以如果我們直接使用「資產差」當作loss的話,只會讓機器選擇do_nothing而已。

2. 平衡買、賣、do_nothing的loss計算

這個應該是全部當中最困難的,我們要考慮很多面向。 如果將do_nothingloss下降,勢必最後又會全部都是do_nothing

我們要鼓勵買,也鼓勵賣,同時又希望在特殊情況下實行do_nothing,這是很矛盾的,很容易就偏往某一邊...

我們必須要修改環境的loss同時,要考慮例外情況。 所以我自己實測不少次,以下是我的測試進化史

  • 前n次測試 : 都是全部「do_nothing」
  • 第二種測試 : 意外的情況下,同時有「買、賣、do_nothing」,且結果還不錯。 但我知道這是錯的reward定義,當訓練多次一點或是使用全部的dataset時,最後結果就會變成「賣」
  • 第三種測試 : 為了要「強迫機器買」,我透過計數不動作來給予「不買」逞罰,包括賣和do_nothing,但因為我的環境「資產」的算法問題,所以在做選擇時,機器發現「賣」跟「買」是一樣的,甚至「賣不好」還會有懲罰,所以最後機器很少會選擇「賣」
    • https://ithelp.ithome.com.tw/upload/images/20190929/20120140Zc44U8QTjV.png
  • 接下來的修改就先留到明天囉~

可以發現,訓練出來的「買」並不是隨便亂買的! 低峰容易進場,代表這樣計算loss是可行的 !!

~ WOW ~這樣也可以? 這樣的loss? 人類自定的loss?

其實我看到也是滿驚訝的 (雖然我改很~~~~~~多次),這是第一次嘗試,也驗證了我對loss的直覺。 今天的程式碼只會放上主要程式,不會放上環境 (因為超級亂Orz..)。 今天的進度條就先這樣吧XD 明天把它改完...

參考

一个很有用的函数 tf.py_func


上一篇
沒有實作所以只好講幹話系列(四) :: 淺談Reinforcement Learning (RL)
下一篇
偏門RL實測 :: 調出一個合適的環境參數 !!
系列文
AI可以分析股票嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言